//
//  开发流程.h
//  MeiTuanHD
//
//  Created by Hanyang Li on 2021/8/27.
//

#pragma mark - 第一天

 一. 创建项目配置基本选项
1. Version
2. Build
3. 支持最低版本
4. 配置启动图
5. Status Bar Style
6. Bundle Name
7. Icon及其他图片素材

 二. 搭建项目目录结构
1. 增加类前缀
2. 删除 Main 直接删除 plist 的这个键值  --> Main storyboard file base name
3. 创建 HomeVC, 重写 init 方法设置布局
4. 设置背景颜色 --> 引入宏定义文件 --> __OBJC__ --> 新的NSLog

 三. 导航栏
1.设置背景颜色 --> 颜色宏定义 --> 全局颜色宏定义
2.设置导航栏背景 --> 创建一个父类导航控制器 --> 重写 initialize --> 设置导航栏 bar 的背景图 --图像的拉升

 四. 设置右边导航栏按钮
1.创建 UIBarButtonItem 的分类 --> 分类创建一个按钮并设置成 customView 返回
2.调整 UIBarButtonItem 的宽度 --> 获取 customView --> 通过 UIView+HMCategory 的分类来设置位置

 五. 设置左边导航栏按钮
1. Logo --> 使用系统的 BarButton 创建方法
   1.1 显示原图 -->  image 方法后面拼接 --> 资源文件夹中选中属性
   1.2 设置 BarButton 不能点击 --> enabled 设置 NO
2. 自定义导航栏公用View --> xib 进行布局(按钮和 image 合二为一 / 2个 Label 上下零间距，不要设置高度。会有优先级约束的问题，点击修复即可)
   --> 创建一个类，提供加载 xib 方法，并且和 xib 绑定
3. homeVC 中进行加载
4. 抽取公用的下拉菜单View --> 使用 xib 进行布局 --> 创建类进行绑定
5. 给导航栏按钮增加按钮点击事件
  5.1 .h 增加属性还是 .m 增加属性
  5.2 .m 中增加属性，那么还需要提供一个方法用来进行按钮的 target: action：
  5.3  homeVC中，给每个导航栏 View 增加按钮方法

六. 设置分类按钮点击
 1.点击创建 popover
 2.创建内容控制器 --> 添加下拉菜单 --> 内容控制器大小 preferredContentSize
 3.解决分类视图中 tableView 不显示的问题:
   3.1 当一个较大的视图，放到较小的视图里，视图就会发生压缩行为
   3.2 autolayout 会勾选autoresizingMask 相关的属性，导致压缩/拉伸时，视图也会跟着变化，解决方案: autoresizingMask = None;
4.数据转模型 --> YYModel --> cocoapods 进行安装
   4.1 pod init --> pod install --no-repo-update 进行快速安装
   4.2 [模型的类名 yy_model...;dict]
5.显示左边表格数据
  5.1 dropdownView 增加 categoryArray 属性
  5.2 categoryVC 中，通过categoryArray 属性来传值
  5.3 dropdownView设置代码及数据源，实现对应的方法
6.显示右边表格数据
  6.1 增加2个表格属性
  6.2 想知道右边显示的东西 --> 先要知道左边选中的是哪个模型 --> tableView 点击 cell 的方法记录选中的模型 --> 需要生成一个属性
  6.3 实现表格选中的方法，记录左边选中的模型，刷新右边表格
  6.4 依次实现返回行数，及设置 cell 内容的方法，在这些方法中，区分左右表格，按照对应的数据进行设置
7.表格显示的优化
  7.1 左边表格显示箭头
  7.2 左边表格显示图像及选中图像
  7.3 设置cell背景图像，记得拉伸图像以及系统分割线
8.表格 cell 的封装
  8.1 创建 cell 类
  8.2 将 cell 创建的代码移植到自定义的 cell 的类方法中即可

七. 设置区域按钮点击
1.创建 districtVC
2.在 homeVC 中点击区域按钮的时候，设置 popover 弹出
3.districtVC 加载 dropdownView，记得设置 Y 值下移，以及设置大小
4.在 xib 中进行导航栏 view 的搭建
  4.1 当出现按钮/一个 Label/ 一个 Image 的时候，思考能否使用1个按钮来完成
  4.2 当 imageView 等无法响应点击事件的控件，不会影响按钮的布局顺序

#pragma mark - 第二天
一. 切换城市点击
1. 创建 cityVC, 使用 xib 进行布局
2. districtVC 中，点击进行切换 --> 使用模态视图
   2.1 呈现样式: formSheet
   2.2 转场样式: 水平翻转
   2.3 消失之前的控制器: 如果父子控制器的层级关系存在，父控制器消失，子控制器肯定也会消失
   2.4 使用根控制器去弹出模态视图

二. 显示分组城市数据
1.设置表格的代理及数据源，生成属性
2.加载 plist 文件，通过 YYModel 转模型。
3.实现表格的数据源方法 --> 分组
4.设置分组标题显示，索引显示
5.设置索引颜色 tintColor / sectionIndexColor

三. 设置搜索框
1.背景图设置，边距设置，占位文字设置
2.实现搜索框的代理方法，监听文本框开始编辑，结束编辑
3.实现开始编辑，结束编辑对应的方法
4.修改取消按钮:遍历子视图，如果发现子视图是一个按钮之类，那么就修改这个按钮
5.遮盖按钮设置: 使用 xib 进行搭建，设置透明度为0，之后更改透明度即可
6.创建搜索结果控制器 --> tableVC
7.cityVC中，添加一个 weak 属性的 citySearchVC, 实现懒加载
 7.1 创建 VC
 7.2 添加子控制器 实现1个控制器里显示另一个控制器的内容 VC 强引用 View
 7.3 添加 view
 7.4 布局
 7.5 给属性赋值
8.实现搜索框的文字改变的代理方法，根据文字的长度来控制器结果控制器的显示与隐藏
9.设置搜索结果控制器的布局: Masonry 框架/ AutoLayout框架

四. 实现实时搜索
1.接收 cityVC 中搜索框的文字
  1.1 citySearchVC 中增加属性
  1.2 重写 searchText 的 set 方法
  1.3 cityVC 中，文字发生改变的时候，需要进行传值
2.加载中的城市数据
  2.1 增加模型: cityModel / districtModel
  2.2 cityModel 的.m文件，需要设置 NAArray 将来按照那个模型去进行解析返回容器类中的所需要存放的数据类型（以 Class 或者 Class Name 的形式）。modelContainerPropertyGenericClass
  2.3 生成一个可变的数据，viewDidLoad 进行加载 plist 并转模型的操作
3.setSearchText 方法中: 进行数据处理
  3.1 copy
  3.2 转换小写
  3.3 删除旧的数据
  3.4 遍历数据，进行判断，判断中文是否包含,全拼，以及首字母缩写是否包含
  3.5 将查询到的结果添加到结果数据中
  3.6 刷新表格
4.实现表格相关的方法，设置分组标题

五.选中城市的通知发送
1. 发送通知给 homeVC
2. const 文件的引用
3.需要一个选中的城市名属性进行选中的谁

六.区域数据的显示
1.点击区域按钮的时候，判断是否有选中的城市，如果有，那么加载cities.plist进行逻辑判断。如果发现转换后的模型name 跟选中的城市名一样，那么就可以将子区域数据，逐层的传递给下拉菜单属性
2.将原有的数据源的方法，在增加一层判断，判断是否是分类数据，还是区域数据

七.区域及分类通知的发送
1.如果选中的右边，直接发送通知，发送2个参数: 左边模型，右边的标题名称
2.如果选中的左边，判断如果没有子数据，才发送通知，发送一个参数:左边模型
3.homeVC 中进行通知的注册，实现通知绑定的方法
4.通知的方法中，还要取消popover的显示

八.排序的通知发送
1.加载 plist 转模型
2.循环创建7个按钮
3.设置 popover 大小
4.实现按钮点击发送通知
5.在 homeVC 中实现通知的方法

九.更改导航栏View的文字
1.生成对应的导航栏 view 的属性
2.创建导航栏按钮的时候，进行属性的赋值
3.对应的通知中，按照规则进行设置标题和子标题
4.设置了导航栏文字的默认值
5.设置了分类图标的改变
6.调整了标题和子标题的大小
7.设置压缩优先级 --> 优先级越高 --> 优先被压缩


#pragma mark - 第三天
一。 加载团购cell
1.创建 cell,使用 xib，同时创建一个类进行加载
2.显示 cell
  2.1 修改重用标识符 --> cell设置一个
  2.2 注册 cell
  2.3 设置 cell 的大小 --> init -->layout.itemSize
  2.4 数据源方法中，修改 cell 的类
3. 显示 cell 的细节优化
  3.1 实现屏幕旋转的方法 --> 获取列数 --> 计算出合适的间距
  3.2 调用出 sectionInset / minimumLineSpacing 设置间距
  3.3 viewDidLoda 中，调用屏幕旋转方法

二. 集成大众点评 SDK
1.记得将开发者注册后的 appKey appSecret 写入 DPAPI.h 中
2.在需要发送请求的地方
  2.1 创建 DPAPI
  2.2 拼接参数
  2.3 发送请求 --> URL 不需要前缀
3.实现请求代理方法 -->请求成功/失败
4.分类参数的正确发送
 4.1 发送右边 右边有值，且不等于 “全部”
 4.2 发送左边 没有子分类数据，就发送左边，且不等于"全部”
 4.3 不发送 没有需求进行筛选 或者 点击了 @“全部分类”
5.区域参数及排序参数的发送
 5.1 区域参数的设置，参考分类参数的设置
 5.2 排序参数，只需要获取的 value 值即可
6.数据转模型
 6.1 按照接口字段生成模型文件
 6.2 请求成功解析数据 --> 一定要找到 Array --> result[@"deals"]
 6.3 模型的字段和 JSON 的字段不一致,需要指定一下

三.显示团购 cell 数据
1.homeVC 增加 dealArray 数据，解析到数据时，添加到此数据中
2.调整 collectionView 的数据源方法
3.dealCell 增加模型属性，并重写 set 方法
4.导入 SDWebImage 框架
5.价格显示的优化
  5.1 查找小数点位置
  5.2 判断有没有找到小数点位置
  5.3 如果找到了小数点位置 总长度 - 小数点的位置 > 3 需要截取
  5.4 重新赋值 将字符串转换成 float 类型，再赋值
6.价格删除线的处理
  6.1 方法一: 画线
  6.2 方法二: 画矩形 -->  高度为1
7.处理新单的显示
  7.1 获取当前的日期
  7.2 创建日期格式化的类
  7.3 设置转换的格式
  7.4 将日期转化成字符串
  7.5 比较2个字符串 隐藏: 当前日期 发布日期 == YES

四. AwesomeMenu的添加
1. 建议不使用 pod 添加此框架
2. 创建中间按钮以及周边的四个按钮
3. 设置一些属性: 禁止旋转，弹出角度，按钮位置
4. 添加代理方法: 1个必须实现的(进行版本跳转的逻辑处理)，4个可选(更改透明度/图像/增加动画)

五. 添加刷新功能
 1.vlewDidLoad中添加刷新功能
  1.1 添加下拉刷新 mj_header = MJRefreshNormalHeader
  1.2 一开始就刷新 --> 进入刷新状态 --> 就会自动调用上方 block 绑定的方法 mj_header beginRefreshing
  1.3 添加上拉加载 mj_footer = MJRefreshAutoNormalFooter
  1.4 一开始就隐藏上拉加载控件 mj_footer.hidden = YES
 // *1.5 请求成功以及请求失败，都需要加入停止刷新控件的方法
 // *1.6 加载成功，恢复底部控件的显示
 2.完善请求成功: 6个步骤
  2.1 屏蔽请求: 进度指示器/最后一次请求
  2.2 获取数据: 只有加载数据的时候,才需要把之前的数据清空 ,拼接新的数据,获取团购总数
  2.3 停止刷新
  2.4 刷新表格
  2.5 控制底部刷新控件的显示与隐藏 :获取服务器返回数据的总是 == self.dealArray.count 相等就代表没有数据了,Hidden
  2.6 没有数据的时候,显示无数据图像 : hidden ? 有数据的时候就隐藏 --> self.daelArray.count != 0
3.完善请求失败: 4步骤
  3.1 屏蔽请求: 进度指示器 / 最后一次请求
  3.2 停止刷新控件
  3.3 提示用户加载失败:进度指示器 / 显示无数据图像
  3.4 页码自减

#pragma mark - 第四天
一. 加载团购详情
 1.创建详情控制器
 2.增加模型的属性 --> h5 URL
 3.homeVC 点击 cell 弹出
 4.detailVC 加载H5网页

二. 加载右边的详情
1.需要对 ID 进行截取处理 --> rangeOfString
2.需要对网页进行删除代码的处理 --> WebView 与 JS 之间的通讯 --> stringByEvaluatingJavaScriptFromString
  2.1 获取网页元素 @"document.getElementsByTagName('html')[0].outerHTML;"
  2.2 获取标签内容 @"var header = document.getElementsByTagName('header')[0];"
  2.3 删除标签内容 @"header.parentNode.removeChild(header);"
3.细节处理
  3.1 内容向下偏移
  3.2 背景颜色
  3.3 加载进度指示器 --> 勾选属性面板中的2个选项
  3.4 当网页加载完成 --> 停止进度指示器的动画 -->  将 JS 代码放入到此方法中

三. 显示左边详情
1.布局导航栏View
2.布局中间的控件
3.布局底部4个按钮
4.处理细节: 图像的占位图 / 收藏按钮选中背景 / 4个按钮选中背景 / 取消4个按钮用户交互 / 设置当前控制器支持的屏幕方法
5.显示过期退款及随时退款: --> 首页的接口中，没有对应的字段 --> 进入详情重新发送请求
  5.1 发送请求
  5.2 获取数据 --> 转模型  --> 字典套字典(不需要框架做任何事情) --> 字典需要生成模型
  5.3 获取按钮，更改 select 状态
6.倒计时的处理
  6.1 获取当前的时间
  6.2 创建日期格式化的类
  6.3 设置转换的格式
  6.4 转换日期格式 --> 模型 字符串 --> NSDate
  6.5 给截止日期增加一天
  6.6 设置要比较的组件
  6.7 比较

四.设置搜索控制器 --> 公用控制器的抽取
1.创建 searchVC --> 设置导航栏 --> titleView
2.抽取所有公用的代码到 baseCollectionVC 中
3.首页网路请求参数，不能抽取，需要放在 homeVC中
4.父类提供 setParams: 方法,由子类实现，并在 BaseVC 中调用此方法
5.HomeVC 中4个通知: m之前是直接调用 loadNewDeal 方法，此时需要更换成刷新框架的刷新方法
6.searchVC 实现搜索数据
  6.1 监听搜索按钮的点击 --> searchBar 设置代理
  6.2 代理方法中，调用框架的刷新方法 --> 绑定了加载新数据的代码 --> 加载 loadDeal 方法(设置参数)
  6.3 searchVC 实现 setParams 方法来设置参数
  6.4 searchVC 细节优化: city / keywork

五. 地图板块
1. 创建mapVC,使用 xib,生成属性的时候,还需要导入 MapKit 框架以及头文件
2. 用户定位，使用位置管理器进行授权(1.写方法 2.配置 plist). 调用跟踪的方法
3.获取数据: mapView 代理方法中进行. regionDidchange 方法中发送请求
4.添加大头针:数据转模型，遍历所有的模型数据，添加大头针


#pragma mark - 第五天
一.地图板块完善
1.处理大头针重复添加的问题
  1.1 每次添加之前，先删除旧的数据
  1.2 判断地图如果已经添加了此大头针模型,就跳过，否则就添加
      记得重写大头针模型的 isEqual 方法
      containsObject: 内部会调用 isEqual 方法
      isEqual 方法： 比较的是哈希值，其中包括了时间

2.自定义大头针 View: 需要使用返回大头针 View 的方法来自定义
  2.1 如果发现是系统的大头针模型，就 return nil.
  2.2 如果发现是自己需要定义的大头针模型，就自定义 --> 参考 tableViewCell
3.显示不同的图像
  3.1 增加大头针模型的属性: icon 属性
  3.2 遍历服务器数据的时候 设置 icon 属性 -->
    抽取工具类：
    3.2.1 提供分类信息的方法
    3.2.2 根据模型来返回对应的地图信息
  3.3 在自定义大头针 View 的地方 , 设置 image 属性为模型的图像
  3.4 一旦实现了自定义大头针的方法,那么可以点击大头针的属性就失效
4.添加地图板块的分类筛选按钮: 只需要拷贝 homeVC 中的对应代码即可
  4.1 通知重复响应的问题:
      视图将要出现的时候，注册通知
      视图将要消失的时候，移除通知
  4.2 通知重新请求数据的问题:
      发送请求之前，删除之前的数据,在调用接口 --> 记得添加 category 参数

二. 创建数据库
1. 创建工具类 --> 此工具类专门解决团购数据相关的问题 --> 通过数据库
2. pod FMDB
3. initialize 方法
 3.1 获取文件路径
 3.2 创建数据库
 3.3 判断是否打开
 3.4 创建表 CREATE TABLE IF NOT EXISTS : 创建表如果不存在
4.添加数据
 4.1 将模型转换成 NSData 自定义归档,模型遵守 NSCoding 协议 --> 实现2个方法
     使用框架自带的几个方法，轻松实现归解档
 4.2 使用插入数据的语句:INSERT INTO 表名(列名,列名) VALUES(%@,%@);
5.删除数据: DELETE FROM 表名 WHERE 列名=%@
6.进入详情页面，判断是否添加过当前的模型数据
 6.1 查询数据 @"SELECT COUNT(*) AS deal_count FROM t_collect WHERE deal_id=%@"
 6.2 调用 next --> 只要想获取数据,就必须调用此方法
 6.3 获取数据: 获取 int 类型的数据 intForColumn

三. 收藏板块
1.创建 collectVC --> 跟 homeVC 很像，可以拷贝 homeVC 的代码快速实现
2.实现导航栏相关的设置
3.显示收藏数据
  3.1 每次获取的个数
  3.2 开始查询的位置
  3.3 查询数据 : @"SELECT * FROM t_collect ORDER BY id DESC LIMIT %ld,%ld";
  3.4 判断是否有下一条数据
  3.5 获取数据 --> 解档  --> 还原成模型
  3.6 转换后的模型，添加到临时数组中
4.在收藏板块的 ViewDidLoad 中,通过工具类方法获取第一页的数据并刷新表格
5.实现上拉加载更多收藏
  5.1 页面保持自增
  5.2 调用工具类方法
  5.3 刷新表格
  5.4 停止刷新
  下面两个方法,可以放入数据源的计算行数的方法中
  5.5 控制底部刷新控件的显示和隐藏
  5.6 没有数据的时候,显示无数据图像
6. 修改加载第一页的方法: self.currentPage = 0, 然后调用加载更多的方法
7. 处理收藏板块，点击详情，再点击取消时，如果返回收藏板块的数据刷新
  7.1 deatilVC 点击的时候，调用 block
  7.2 collectVC 创建 deatilVC的时候，设置 block 回调
  7.3  block 回调 --> 删除之前的数据 --> 页码归0 --> 调用加载更多方法

四. 批量删除
1. 点击编辑按钮发生文字改变: 根据item.title属性判断即可
2. 实现 item 文字颜色改变: 自定义的导航栏中，统一设置颜色
3. 实现左边导航栏按钮的数量切换: 编辑时 4个，完成时，1个。 --> 制造4个属性 --> 编辑方法中，进行数量的更改 --> 实现按钮绑定的方法
4. 处理遮盖按钮的显示
  4.1 xib 增加按钮及图像
  4.2 增加模型属性
  4.3 修改 cell 的 set 方法
  4.4 编辑按钮点击时，遍历数据修改模型属性，重新加载即可
5.处理遮盖按钮的方法: 显示打钩图像
  5.1 增加模型属性
  5.2 修改 cell 的 set 方法
  5.3 设置按钮的点击方法: 1. 图像隐藏属性取反  2. 模型数据取反
6.处理导航栏按钮的点击: 编辑 / 全选 / 全不选
7.删除按钮状态更改 --> cell 添加 block 传值 --> 只要点击了 cell 就遍历所有的数据，通过遍历数据来判断删除按钮是否可用
8.删除按钮的点击
  8.1 临时数组记录要删除的数据
  8.2 遍历数据 不能载遍历可变数据的时候，对数据进行更改，在遍历完成才可以
  8.3 如果打钩为 YES，就代表要删除数据: 1 记录要删除的数据 2 要删除数据库的数据
  8.4 删除数组数据
  8.5 刷新数据
  8.6 删除按钮不可用
